This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.
Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter. # Tue Jun 7 19:35:18 2022 ——————————
source("tianfengRwrappers.R")
rat Frontier GSE174098 carotid
rat10x <- CreateSeuratObject(Read10X("./rat_scRNAseq/"), names.field = 2, names.delim = "-",
project = "rat", min.cells = 10, min.features = 300) %>%
PercentageFeatureSet(pattern = "^Mt-", col.name = "percent.mt")
table(rat10x$orig.ident)
VlnPlot(rat10x,"nCount_RNA") /
VlnPlot(rat10x,"percent.mt") /
VlnPlot(rat10x, "nFeature_RNA")
rat10x <- rat10x %>% subset(subset = nFeature_RNA > 400 & nFeature_RNA < 4000 &
nCount_RNA > 1000 & nCount_RNA < 30000 & percent.mt< 10) %>%
SCTransform(vars.to.regress = "percent.mt", verbose = F) %>%
RunPCA() %>% FindNeighbors(dims = 1:20) %>%
RunUMAP(dims = 1:20) %>%
FindClusters(resolution = 0.1)

mouse coronary GSE131778
mouse_coronary_countmatrix <- read.csv("./GSE131776_mouse_scRNAseq.txt", sep = "\t")
func <- function(s) {
paste0(strsplit(s, ".", fixed = T)[[1]][2], "_", strsplit(s, ".", fixed = T)[[1]][1])
}
colnames(mouse_coronary_countmatrix) <- lapply(colnames(mouse_coronary_countmatrix), func) # 拆分样本
mousecor <- CreateSeuratObject(counts = mouse_coronary_countmatrix,
project = "mouse_cor", min.cells = 10, min.features = 300) %>% PercentageFeatureSet(pattern = "^mt-", col.name = "percent.mt")
# saveRDS(mousecor,"mousecor.rds")
table(mousecor$orig.ident)
VlnPlot(mousecor,"nCount_RNA") /
VlnPlot(mousecor,"percent.mt") /
VlnPlot(mousecor, "nFeature_RNA")
mousecor <- mousecor %>% subset(subset = nFeature_RNA > 400 & nFeature_RNA < 4000 &
nCount_RNA > 1000 & nCount_RNA < 30000 & percent.mt < 10) %>%
SCTransform(vars.to.regress = "percent.mt", verbose = F) %>%
RunPCA() %>% FindNeighbors(dims = 1:20) %>%
RunUMAP(dims = 1:20) %>%
FindClusters(resolution = 0.1)
table(mousecor$orig.ident)
saveRDS(mousecor,"mousecor.rds")
SMC2
mousecor <- readRDS("mousecor.rds")
f("Prdm16",mousecor, label.size = 7) + theme(legend.text = element_text(size = 20))
umapplot(mousecor_stromal, label.size = 6) + theme(legend.text = element_text(size = 20))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the
existing scale.

mouse carotid scRNAseq GSE155513
dataload
count_mats <- list.files("./GSE155513_RAW/")
count_mats <- count_mats[count_mats != "sampleinfo.txt"]
allList <- lapply(count_mats, function(file) {
dd <- read.table(paste0("./GSE155513_RAW/", file), row.names = 1,stringsAsFactors = F)
colnames(dd) <- as.character(dd['gene',])
dd <- dd[-1,]
CreateSeuratObject(
counts = dd,
project = file, min.cells = 10, min.features = 300
)
})
# 合并seurat对象
mouse_carotid <- merge(allList[[1]],
y = allList[-1], add.cell.ids = count_mats,
project = "mouse_carotid"
)
rm(allList)
# saveRDS(mouse_carotid,"mouse_carotid.rds")
# View(mouse_carotid)
process
mouse_carotid <- readRDS("mouse_carotid.rds")
mouse_carotid <- mouse_carotid %>% PercentageFeatureSet(pattern = "^mt-", col.name = "percent.mt") %>%
subset(subset = nFeature_RNA > 500 & nFeature_RNA < 3000 &
nCount_RNA > 1000 & nCount_RNA < 20000 & percent.mt < 10) %>%
SCTransform(vars.to.regress = "percent.mt", verbose = F) %>%
RunPCA() %>% FindNeighbors(dims = 1:20) %>%
RunUMAP(dims = 1:20) %>%
FindClusters(resolution = 0.1)
saveRDS(mouse_carotid,"mouse_carotid.rds")
SMC

stromal cells
mouse_carotid_stromal <- subset(mouse_carotid,idents = c(0,2,1,7))
mouse_carotid_stromal <- mouse_carotid_stromal %>% RunPCA() %>% FindNeighbors(dims = 1:20) %>%
RunUMAP(dims = 1:20) %>% FindClusters(resolution = 0.1)
mouse_carotid_stromal <- mouse_carotid_stromal %>% FindClusters(resolution = 0.2)
mouse_carotid_stromal <- readRDS("mouse_carotid_stromal.rds")
# saveRDS(mouse_carotid_stromal,"mouse_carotid_stromal.rds")
umapplot(mouse_carotid_stromal)
f("Dlx2",mouse_carotid_stromal) #Dlx2,Dlx5,Dlx6共同定位
分群表
table(group_tab[Dlx5poscells])/table(group_tab)
GSM4705592_RPS003_matrix.txt.gz GSM4705593_RPS004_matrix.txt.gz GSM4705594_RPS011_matrix.txt.gz GSM4705595_RPS012_matrix.txt.gz GSM4705596_RPS007_matrix.txt.gz
0.080645161 0.076949502 0.130000000 0.029882604 0.058282209
GSM4705597_RPS008_matrix.txt.gz GSM4705598_RPS001_matrix.txt.gz GSM4705599_RPS002_matrix.txt.gz GSM4705600_RPS017_matrix.txt.gz GSM4705601_RPS018_matrix.txt.gz
0.004746835 0.039230575 0.003976143 0.093492209 0.095634096
GSM4705602_RPS013_matrix.txt.gz GSM4705603_RPS014_matrix.txt.gz GSM4705604_RPS015_matrix.txt.gz GSM4705605_RPS016_matrix.txt.gz
0.066773504 0.019255456 0.042503503 0.030303030
图

human ds2
p <- multi_featureplot(c("FRZB","SOST","DLX5","DLX6"), ds2, labels = NA, label.size = 6)
ggsave("refds2_SMC2_carotid_stromal.png",plot = p, height = 7, width = 7,device = png)
Warning: Removed 1 rows containing missing values (geom_text).
human bulk RNA-seq GSE120521 carotid stable/unstable FPKM
fpkm2tpm <- function(fpkm){
exp(log(fpkm) - log(sum(fpkm)) + log(1e6))
}
fpkm_matrix <- read.csv("GSE120521_FPKM.csv")
# fpkm_matrix <- distinct(fpkm_matrix) #去除重复行
fpkm_matrix <- fpkm_matrix[!duplicated(fpkm_matrix$name),]
rownames(fpkm_matrix) <- fpkm_matrix$name
fpkm_matrix$name <- NULL
tpm_matrix <- apply(fpkm_matrix, 2, fpkm2tpm)
colSums(tpm_matrix)
group_file <- c("stable","unstable","stable","unstable",
"stable","unstable","stable","unstable")
boxplot(tpm_matrix, las = 2)
expr_mat <- tpm_matrix[!apply(tpm_matrix, 1, function(x){sum(floor(x) == 0)>3}),]
boxplot(expr_mat, las = 2)
library(limma)
expr_mat <- normalizeBetweenArrays(expr_mat)
expr_mat <- log2(expr_mat+1) #使用log2 scale
#PCA
library(ggfortify)
df <- as.data.frame(t(expr_mat))
df$group <- group_file
autoplot(prcomp(df[,1:(ncol(df)-1)]), data=df, colour = 'group')+ theme_bw()
# If the sequencing depth is reasonably consistent across the RNA samples, then the simplest and most robust approach to differential exis to use limma-trend.
fit <- lmFit(expr_mat, group_file)
fit <- treat(fit, lfc=log2(1.2), trend=TRUE)
topTreat(fit, coef=ncol(design))
library(ggpubr)
dat <- expr_mat
design <- model.matrix(~factor(group_file))
fit <- lmFit(dat, design)
fit <- eBayes(fit)
# options(digits = 4)
topTable(fit,coef=2,adjust='BH')
deg <- topTable(fit,coef=2,adjust='BH',number = Inf)
head(deg)
write.csv(deg,"./datatable/stable vs unstable.csv")
## look up FRZB, SOST, PRDM6, OGN
ds1markers[ds1markers$cluster == "SMC2",]$gene
ds2markers[ds2markers$cluster == "SMC3",]$gene
smc2markers <- intersect(ds1markers[ds1markers$cluster == "SMC2",]$gene, ds2markers[ds2markers$cluster == "SMC3",]$gene)
deg[intersect(smc2markers, rownames(deg)),]
ds1markers[ds1markers$cluster == "SMC1",]$gene
ds2markers[ds2markers$cluster == "SMC1",]$gene
SMC1markers <- intersect(ds1markers[ds1markers$cluster == "SMC1",]$gene, ds2markers[ds2markers$cluster == "SMC1",]$gene)
deg[intersect(SMC1markers, rownames(deg)),]

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.
When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).
The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouIAojIFR1ZSBKdW4gIDcgMTk6MzU6MTggMjAyMiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCgpgYGB7cn0Kc291cmNlKCJ0aWFuZmVuZ1J3cmFwcGVycy5SIikKYGBgCgojIyByYXQgRnJvbnRpZXIgKkdTRTE3NDA5OCogY2Fyb3RpZApgYGB7ciBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD04fQpyYXQxMHggPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KFJlYWQxMFgoIi4vcmF0X3NjUk5Bc2VxLyIpLCBuYW1lcy5maWVsZCA9IDIsIG5hbWVzLmRlbGltID0gIi0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2plY3QgPSAicmF0IiwgbWluLmNlbGxzID0gMTAsIG1pbi5mZWF0dXJlcyA9IDMwMCkgJT4lCiAgUGVyY2VudGFnZUZlYXR1cmVTZXQocGF0dGVybiA9ICJeTXQtIiwgY29sLm5hbWUgPSAicGVyY2VudC5tdCIpIAoKdGFibGUocmF0MTB4JG9yaWcuaWRlbnQpClZsblBsb3QocmF0MTB4LCJuQ291bnRfUk5BIikgLwpWbG5QbG90KHJhdDEweCwicGVyY2VudC5tdCIpIC8KVmxuUGxvdChyYXQxMHgsICJuRmVhdHVyZV9STkEiKQoKCnJhdDEweCA8LSByYXQxMHggJT4lIHN1YnNldChzdWJzZXQgPSBuRmVhdHVyZV9STkEgPiA0MDAgJiBuRmVhdHVyZV9STkEgPCA0MDAwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbkNvdW50X1JOQSA+IDEwMDAgJiAgbkNvdW50X1JOQSA8IDMwMDAwICYgcGVyY2VudC5tdDwgMTApICU+JQogICAgU0NUcmFuc2Zvcm0odmFycy50by5yZWdyZXNzID0gInBlcmNlbnQubXQiLCB2ZXJib3NlID0gRikgJT4lIAogICAgUnVuUENBKCkgJT4lIEZpbmROZWlnaGJvcnMoZGltcyA9IDE6MjApICU+JSAKICAgIFJ1blVNQVAoZGltcyA9IDE6MjApICU+JSAKICAgIEZpbmRDbHVzdGVycyhyZXNvbHV0aW9uID0gMC4xKQoKYGBgCgoKYGBge3IgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9M30KdW1hcHBsb3QocmF0MTB4KQptdWx0aV9mZWF0dXJlcGxvdChjKCJBY3RhMiIsIkNubjEiLCJGbjEiLCJMdW0iLCJWY2FtMSIsIkx5NmEiLCJEbHg1IiwiRGx4NiIsIlNvc3QiKSwgcmF0MTB4KQoKCmYoIkJtcHIxYiIsIHJhdDEweCkgLwpmKCJCbXByMWEiLCByYXQxMHgpCnRhYmxlKHJhdDEweCRzZXVyYXRfY2x1c3RlcnMpCgpyYXQxMHgwIDwtIHN1YnNldChyYXQxMHgsaWRlbnQgPSAwKQoKZigiU29zdCIscmF0MTB4KQpuY29sKHN1YnNldChyYXQxMHgwLCBzdWJzZXQgPSBCbXByMWEgPiAwKSkKbmNvbChzdWJzZXQocmF0MTB4MCwgc3Vic2V0ID0gQm1wcjFiID4gMCkpCm5jb2woc3Vic2V0KHJhdDEweDAsIHN1YnNldCA9IEJtcHIxYSA+IDAgJiBCbXByMWIgPiAwKSkKCm5jb2woc3Vic2V0KHJhdDEweDAsIHN1YnNldCA9IFNvc3QgPiAwICYgQm1wcjFiID4gMCkpCm5jb2woc3Vic2V0KHJhdDEweDAsIHN1YnNldCA9IFNvc3QgPiAwICYgQm1wcjFhID4gMCkpCgpuY29sKHJhdDEweDApCmBgYAoKCiMgbW91c2UgY29yb25hcnkgKkdTRTEzMTc3OCoKYGBge3J9Cm1vdXNlX2Nvcm9uYXJ5X2NvdW50bWF0cml4IDwtIHJlYWQuY3N2KCIuL0dTRTEzMTc3Nl9tb3VzZV9zY1JOQXNlcS50eHQiLCBzZXAgPSAiXHQiKQpmdW5jIDwtIGZ1bmN0aW9uKHMpIHsKICBwYXN0ZTAoc3Ryc3BsaXQocywgIi4iLCBmaXhlZCA9IFQpW1sxXV1bMl0sICJfIiwgc3Ryc3BsaXQocywgIi4iLCBmaXhlZCA9IFQpW1sxXV1bMV0pCn0KY29sbmFtZXMobW91c2VfY29yb25hcnlfY291bnRtYXRyaXgpIDwtIGxhcHBseShjb2xuYW1lcyhtb3VzZV9jb3JvbmFyeV9jb3VudG1hdHJpeCksIGZ1bmMpICMg5ouG5YiG5qC35pysCmBgYAoKYGBge3IgZmlnLndpZHRoPSA0LCBmaWcuaGVpZ2h0PTh9Cm1vdXNlY29yIDwtIENyZWF0ZVNldXJhdE9iamVjdChjb3VudHMgPSBtb3VzZV9jb3JvbmFyeV9jb3VudG1hdHJpeCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9qZWN0ID0gIm1vdXNlX2NvciIsIG1pbi5jZWxscyA9IDEwLCBtaW4uZmVhdHVyZXMgPSAzMDApICU+JSAgUGVyY2VudGFnZUZlYXR1cmVTZXQocGF0dGVybiA9ICJebXQtIiwgY29sLm5hbWUgPSAicGVyY2VudC5tdCIpIAoKIyBzYXZlUkRTKG1vdXNlY29yLCJtb3VzZWNvci5yZHMiKQp0YWJsZShtb3VzZWNvciRvcmlnLmlkZW50KQpWbG5QbG90KG1vdXNlY29yLCJuQ291bnRfUk5BIikgLwpWbG5QbG90KG1vdXNlY29yLCJwZXJjZW50Lm10IikgLwpWbG5QbG90KG1vdXNlY29yLCAibkZlYXR1cmVfUk5BIikKCgptb3VzZWNvciA8LSBtb3VzZWNvciAlPiUgc3Vic2V0KHN1YnNldCA9IG5GZWF0dXJlX1JOQSA+IDQwMCAmIG5GZWF0dXJlX1JOQSA8IDQwMDAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuQ291bnRfUk5BID4gMTAwMCAmICBuQ291bnRfUk5BIDwgMzAwMDAgJiBwZXJjZW50Lm10IDwgMTApICU+JQogICAgU0NUcmFuc2Zvcm0odmFycy50by5yZWdyZXNzID0gInBlcmNlbnQubXQiLCB2ZXJib3NlID0gRikgJT4lIAogICAgUnVuUENBKCkgJT4lIEZpbmROZWlnaGJvcnMoZGltcyA9IDE6MjApICU+JSAKICAgIFJ1blVNQVAoZGltcyA9IDE6MjApICU+JSAKICAgIEZpbmRDbHVzdGVycyhyZXNvbHV0aW9uID0gMC4xKQp0YWJsZShtb3VzZWNvciRvcmlnLmlkZW50KQpzYXZlUkRTKG1vdXNlY29yLCJtb3VzZWNvci5yZHMiKQpgYGAKCiMjIyBTTUMyCmBgYHtyIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTN9Cm1vdXNlY29yIDwtIHJlYWRSRFMoIm1vdXNlY29yLnJkcyIpCmYoIlByZG0xNiIsbW91c2Vjb3IsIGxhYmVsLnNpemUgPSA3KSArIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCkpCmBgYAoKCmBgYHtyIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTN9Cm1vdXNlY29yX3N0cm9tYWwgPC0gc3Vic2V0KG1vdXNlY29yLGlkZW50cyA9IGMoMCwxLDIpKQoKbW91c2Vjb3Jfc3Ryb21hbCA8LSBtb3VzZWNvcl9zdHJvbWFsICU+JSBSdW5QQ0EoKSAlPiUgRmluZE5laWdoYm9ycyhkaW1zID0gMToyMCkgJT4lIAogICAgUnVuVU1BUChkaW1zID0gMToyMCkgJT4lIEZpbmRDbHVzdGVycyhyZXNvbHV0aW9uID0gMC4yKQptb3VzZWNvcl9zdHJvbWFsIDwtIG1vdXNlY29yX3N0cm9tYWwgJT4lIEZpbmRDbHVzdGVycyhyZXNvbHV0aW9uID0gMC4yKQoKCm1vdXNlY29yX3N0cm9tYWwgPC0gcmVhZFJEUygibW91c2Vjb3Jfc3Ryb21hbC5yZHMiKQoKdW1hcHBsb3QobW91c2Vjb3Jfc3Ryb21hbCwgbGFiZWwuc2l6ZSA9IDYpICsgdGhlbWUobGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSkKbXVsdGlfZmVhdHVyZXBsb3QoYygiQWN0YTIiLCJDbm4xIiwiRm4xIiwiTHVtIiwiVmNhbTEiLCJMeTZhIiwiRGx4NSIsIkRseDYiKSwgbW91c2Vjb3Jfc3Ryb21hbCxsYWJlbHMgPSBOQSkKCgpsZXZlbHMoSWRlbnRzKG1vdXNlY29yX3N0cm9tYWwpKSA8LSBjKCJTTUMxIiwiRmlicm9ibGFzdDEiLCJGaWJyb215b2N5dGUiLCJTTUMxIiwiRmlicm9ibGFzdDIiLCJTTUMyIikKZigiQWN0YTIiLG1vdXNlY29yX3N0cm9tYWwsbGFiZWwuc2l6ZSA9IDYpCnAgPC0gbXVsdGlfZmVhdHVyZXBsb3QoYygiQWN0YTIiLCJDbm4xIiwiRm4xIiwiTHVtIiwiVmNhbTEiLCJMeTZhIiwiRGx4NSIsIkRseDYiLCJMZ2FsczMiKSxtb3VzZWNvcl9zdHJvbWFsLGxhYmVscyA9IE5BLGxhYmVsLnNpemUgPSA2KQpnZ3NhdmUoIm5hdG1lZF9tb3VzZV9jb3JvbmFyeV9zdHJvbWFsMi5wbmciLHBsb3QgPSBwLCBoZWlnaHQgPSAxMiwgd2lkdGggPSAxNixkZXZpY2UgPSBwbmcpCnVtYXBwbG90KG1vdXNlY29yX3N0cm9tYWwsIGxhYmVsLnNpemUgPSA2KSArIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCkpCmBgYAoKIyBtb3VzZSBjYXJvdGlkIHNjUk5Bc2VxICpHU0UxNTU1MTMqCiMjIyBkYXRhbG9hZApgYGB7cn0KY291bnRfbWF0cyA8LSBsaXN0LmZpbGVzKCIuL0dTRTE1NTUxM19SQVcvIikKY291bnRfbWF0cyA8LSBjb3VudF9tYXRzW2NvdW50X21hdHMgIT0gInNhbXBsZWluZm8udHh0Il0KYWxsTGlzdCA8LSBsYXBwbHkoY291bnRfbWF0cywgZnVuY3Rpb24oZmlsZSkgewogIGRkIDwtIHJlYWQudGFibGUocGFzdGUwKCIuL0dTRTE1NTUxM19SQVcvIiwgZmlsZSksIHJvdy5uYW1lcyA9IDEsc3RyaW5nc0FzRmFjdG9ycyA9IEYpCiAgY29sbmFtZXMoZGQpIDwtIGFzLmNoYXJhY3RlcihkZFsnZ2VuZScsXSkKICBkZCA8LSBkZFstMSxdCiAgQ3JlYXRlU2V1cmF0T2JqZWN0KAogICAgY291bnRzID0gZGQsCiAgICBwcm9qZWN0ID0gZmlsZSwgbWluLmNlbGxzID0gMTAsIG1pbi5mZWF0dXJlcyA9IDMwMAogICkKfSkKIyDlkIjlubZzZXVyYXTlr7nosaEKbW91c2VfY2Fyb3RpZCA8LSBtZXJnZShhbGxMaXN0W1sxXV0sIAogIHkgPSBhbGxMaXN0Wy0xXSwgYWRkLmNlbGwuaWRzID0gY291bnRfbWF0cywKICBwcm9qZWN0ID0gIm1vdXNlX2Nhcm90aWQiCikKcm0oYWxsTGlzdCkKCiMgc2F2ZVJEUyhtb3VzZV9jYXJvdGlkLCJtb3VzZV9jYXJvdGlkLnJkcyIpCiMgVmlldyhtb3VzZV9jYXJvdGlkKQpgYGAKCiMjIyBwcm9jZXNzCmBgYHtyfQptb3VzZV9jYXJvdGlkIDwtIHJlYWRSRFMoIm1vdXNlX2Nhcm90aWQucmRzIikKCm1vdXNlX2Nhcm90aWQgPC0gbW91c2VfY2Fyb3RpZCAlPiUgIFBlcmNlbnRhZ2VGZWF0dXJlU2V0KHBhdHRlcm4gPSAiXm10LSIsIGNvbC5uYW1lID0gInBlcmNlbnQubXQiKSAlPiUKc3Vic2V0KHN1YnNldCA9IG5GZWF0dXJlX1JOQSA+IDUwMCAmIG5GZWF0dXJlX1JOQSA8IDMwMDAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuQ291bnRfUk5BID4gMTAwMCAmICBuQ291bnRfUk5BIDwgMjAwMDAgJiBwZXJjZW50Lm10IDwgMTApICU+JQogICAgU0NUcmFuc2Zvcm0odmFycy50by5yZWdyZXNzID0gInBlcmNlbnQubXQiLCB2ZXJib3NlID0gRikgJT4lIAogICAgUnVuUENBKCkgJT4lIEZpbmROZWlnaGJvcnMoZGltcyA9IDE6MjApICU+JSAKICAgIFJ1blVNQVAoZGltcyA9IDE6MjApICU+JSAKICAgIEZpbmRDbHVzdGVycyhyZXNvbHV0aW9uID0gMC4xKQoKc2F2ZVJEUyhtb3VzZV9jYXJvdGlkLCJtb3VzZV9jYXJvdGlkLnJkcyIpCmBgYAoKIyMjIFNNQwpgYGB7cn0KbW91c2VfY2Fyb3RpZCA8LSByZWFkUkRTKCJtb3VzZV9jYXJvdGlkLnJkcyIpCnVtYXBwbG90KG1vdXNlX2Nhcm90aWQpCnVtYXBwbG90KG1vdXNlX2Nhcm90aWQsZ3JvdXAuYnkgPSAib3JpZy5pZGVudCIsbGFiZWwgPSBGKQpmKCJQcmRtMTYiLG1vdXNlX2Nhcm90aWQpICNTTUMKZigiTHk2YSIsbW91c2VfY2Fyb3RpZCkgI1NFTS1saWtlIGNlbGxzCgptdWx0aV9mZWF0dXJlcGxvdChjKCJCbXAyIiwiQm1wNCIsIkJtcDYiKSxtb3VzZV9jYXJvdGlkKQoKIyMgQk1QNCDlnKjov5nph4xFQ+eahCrlpKfpg6jliIYq5Lit6KGo6L6+77yM6ICM5Zyo5Lq657G75qC35pys5LitQk1QNCsgRUPnu4bog57mmK/lsJHmlbDnmoQKbWFya2VycyA8LSBGaW5kQWxsTWFya2Vycyhtb3VzZV9jYXJvdGlkLGxvZ2ZjLnRocmVzaG9sZCA9IDAuNSxtaW4uZGlmZi5wY3QgPSAwLjIsIG9ubHkucG9zID0gVCkKYGBgCiMjIyBzdHJvbWFsIGNlbGxzCmBgYHtyIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTN9Cm1vdXNlX2Nhcm90aWRfc3Ryb21hbCA8LSBzdWJzZXQobW91c2VfY2Fyb3RpZCxpZGVudHMgPSBjKDAsMiwxLDcpKQptb3VzZV9jYXJvdGlkX3N0cm9tYWwgPC0gbW91c2VfY2Fyb3RpZF9zdHJvbWFsICU+JSBSdW5QQ0EoKSAlPiUgRmluZE5laWdoYm9ycyhkaW1zID0gMToyMCkgJT4lIAogICAgUnVuVU1BUChkaW1zID0gMToyMCkgJT4lIEZpbmRDbHVzdGVycyhyZXNvbHV0aW9uID0gMC4xKQptb3VzZV9jYXJvdGlkX3N0cm9tYWwgPC0gbW91c2VfY2Fyb3RpZF9zdHJvbWFsICU+JSBGaW5kQ2x1c3RlcnMocmVzb2x1dGlvbiA9IDAuMikKCm1vdXNlX2Nhcm90aWRfc3Ryb21hbCA8LSByZWFkUkRTKCJtb3VzZV9jYXJvdGlkX3N0cm9tYWwucmRzIikKIyBzYXZlUkRTKG1vdXNlX2Nhcm90aWRfc3Ryb21hbCwibW91c2VfY2Fyb3RpZF9zdHJvbWFsLnJkcyIpCgp1bWFwcGxvdChtb3VzZV9jYXJvdGlkX3N0cm9tYWwpCmYoIkRseDIiLG1vdXNlX2Nhcm90aWRfc3Ryb21hbCkgI0RseDIsRGx4NSxEbHg25YWx5ZCM5a6a5L2NCmBgYAoKIyMjIyDliIbnvqTooagKYGBge3IgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9M30KRGx4NXBvc2NlbGxzIDwtIFdoaWNoQ2VsbHMobW91c2VfY2Fyb3RpZF9zdHJvbWFsLCBleHByZXNzaW9uID0gYERseDZgID4gMCAmIGBEbHg1YCA+IDApCmdyb3VwX3RhYiA8LSBJZGVudHMobW91c2VfY2Fyb3RpZF9zdHJvbWFsKQp0YWJsZShncm91cF90YWJbRGx4NXBvc2NlbGxzXSkvdGFibGUoZ3JvdXBfdGFiKSAKIyDlnKhjbHVzdGVyNSDmnIk0My44JeeahOe7huiDnuihqOi+vkRMWDXvvIwzOC40JeeahOe7huiDnuihqOi+vkRMWDYsMjAuMiXnmoTnu4bog57ooajovr7kuKTogIUKCiMjIOWFs+S6juagt+acrOS/oeaBrwpEbHg1cG9zY2VsbHMgPC0gV2hpY2hDZWxscyhtb3VzZV9jYXJvdGlkX3N0cm9tYWwsIGlkZW50cyA9ICJETFggU01DIikKZ3JvdXBfdGFiIDwtIG1vdXNlX2Nhcm90aWRfc3Ryb21hbCRvcmlnLmlkZW50CnRhYmxlKGdyb3VwX3RhYltEbHg1cG9zY2VsbHNdKS90YWJsZShncm91cF90YWIpIAp0YWJsZShncm91cF90YWJbRGx4NXBvc2NlbGxzXSkKYGBgCgojIyMjIOWbvgpgYGB7ciBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD0zfQpsZXZlbHMoSWRlbnRzKG1vdXNlX2Nhcm90aWRfc3Ryb21hbCkpIDwtIGMoIlNFTSBjZWxsIiwiRmlicm9ibGFzdDEiLCJTTUMxIiwiU01DMiIsIkZpYnJvYmxhc3QyIiwiRExYIFNNQyIsIlVuYW5ub3RhdGVkIiwiVW5hbm5vdGF0ZWQiKQp1bWFwcGxvdChtb3VzZV9jYXJvdGlkX3N0cm9tYWwsbGFiZWwuc2l6ZSA9IDYsbGFiZWwgPSBGKSArIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF9ibGFuaygpKQoKcCA8LSBtdWx0aV9mZWF0dXJlcGxvdChjKCJBY3RhMiIsIkNubjEiLCJGbjEiLCJMdW0iLCJWY2FtMSIsIkx5NmEiLCJEbHg1IiwiRGx4NiIsIkxnYWxzMyIpLG1vdXNlX2Nhcm90aWRfc3Ryb21hbCxsYWJlbHMgPSBOQSwgbGFiZWwuc2l6ZSA9IDYpCmdnc2F2ZSgiY2lyX21vdXNlX2Nhcm90aWRfc3Ryb21hbDIucG5nIixwbG90ID0gcCwgaGVpZ2h0ID0gMTIsIHdpZHRoID0gMTYsZGV2aWNlID0gcG5nKQpEb3RwbG90KGMoIkFjdGEyIiwiQ25uMSIsIkZuMSIsIkx1bSIsIlZjYW0xIiwiTHk2YSIsIkRseDUiLCJEbHg2IiwiU29zdCIpLG1vdXNlX2Nhcm90aWRfc3Ryb21hbCkKCkRMWHBvc1NNQ19tYXJrZXJzIDwtIEZpbmRNYXJrZXJzKG1vdXNlX2Nhcm90aWRfc3Ryb21hbCwgaWRlbnQuMSA9ICJETFggU01DIiwgbG9nZmMudGhyZXNob2xkID0gMC40LCBvbmx5LnBvcyA9IFQsIG1pbi5kaWZmLnBjdCA9IDAuMikKZigiRGx4NSIsbW91c2VfY2Fyb3RpZF9zdHJvbWFsKQoKbGlicmFyeShvcmcuTW0uZWcuZGIpCkdPX2RvdHBsb3Qocm93bmFtZXMoRExYcG9zU01DX21hcmtlcnMpLCBPcmdEYiA9IG9yZy5NbS5lZy5kYikKYGBgCiMgaHVtYW4gZHMyCmBgYHtyfQpwIDwtIG11bHRpX2ZlYXR1cmVwbG90KGMoIkFDVEEyIiwiQ05OMSIsIkZOMSIsIkxVTSIsIlZDQU0xIiwiTFk2QSIsIkRMWDUiLCJETFg2IiwiTEdBTFMzIiwiU09TVCIpLCBkczIsIGxhYmVscyA9IE5BLCBsYWJlbC5zaXplID0gNikKCmdnc2F2ZSgicmVmZHMyX2Nhcm90aWRfc3Ryb21hbC5wbmciLHBsb3QgPSBwLCBoZWlnaHQgPSAxMiwgd2lkdGggPSAxMixkZXZpY2UgPSBwbmcpCgoKcCA8LSBtdWx0aV9mZWF0dXJlcGxvdChjKCJGUlpCIiwiU09TVCIsIkRMWDUiLCJETFg2IiksIGRzMiwgbGFiZWxzID0gTkEsIGxhYmVsLnNpemUgPSA2KQpnZ3NhdmUoInJlZmRzMl9TTUMyX2Nhcm90aWRfc3Ryb21hbC5wbmciLHBsb3QgPSBwLCBoZWlnaHQgPSA3LCB3aWR0aCA9IDcsZGV2aWNlID0gcG5nKQpgYGAKCgojIGh1bWFuIGJ1bGsgUk5BLXNlcSAqR1NFMTIwNTIxKiBjYXJvdGlkIHN0YWJsZS91bnN0YWJsZSBGUEtNCmBgYHtyfQpmcGttMnRwbSA8LSBmdW5jdGlvbihmcGttKXsKICBleHAobG9nKGZwa20pIC0gbG9nKHN1bShmcGttKSkgKyBsb2coMWU2KSkKfQoKZnBrbV9tYXRyaXggPC0gcmVhZC5jc3YoIkdTRTEyMDUyMV9GUEtNLmNzdiIpCiMgZnBrbV9tYXRyaXggPC0gZGlzdGluY3QoZnBrbV9tYXRyaXgpICPljrvpmaTph43lpI3ooYwKZnBrbV9tYXRyaXggPC0gZnBrbV9tYXRyaXhbIWR1cGxpY2F0ZWQoZnBrbV9tYXRyaXgkbmFtZSksXQpyb3duYW1lcyhmcGttX21hdHJpeCkgPC0gZnBrbV9tYXRyaXgkbmFtZQpmcGttX21hdHJpeCRuYW1lIDwtIE5VTEwKCnRwbV9tYXRyaXggPC0gYXBwbHkoZnBrbV9tYXRyaXgsIDIsIGZwa20ydHBtKQpjb2xTdW1zKHRwbV9tYXRyaXgpCgpncm91cF9maWxlIDwtIGMoInN0YWJsZSIsInVuc3RhYmxlIiwic3RhYmxlIiwidW5zdGFibGUiLAogICAgICAgICAgICAgICAgInN0YWJsZSIsInVuc3RhYmxlIiwic3RhYmxlIiwidW5zdGFibGUiKQpib3hwbG90KHRwbV9tYXRyaXgsIGxhcyA9IDIpCgpleHByX21hdCA8LSB0cG1fbWF0cml4WyFhcHBseSh0cG1fbWF0cml4LCAxLCBmdW5jdGlvbih4KXtzdW0oZmxvb3IoeCkgPT0gMCk+M30pLF0KCmJveHBsb3QoZXhwcl9tYXQsIGxhcyA9IDIpCgpsaWJyYXJ5KGxpbW1hKQpleHByX21hdCA8LSBub3JtYWxpemVCZXR3ZWVuQXJyYXlzKGV4cHJfbWF0KQpleHByX21hdCA8LSBsb2cyKGV4cHJfbWF0KzEpICPkvb/nlKhsb2cyIHNjYWxlCgojUENBCmxpYnJhcnkoZ2dmb3J0aWZ5KSAKZGYgPC0gYXMuZGF0YS5mcmFtZSh0KGV4cHJfbWF0KSkgCmRmJGdyb3VwIDwtIGdyb3VwX2ZpbGUgCmF1dG9wbG90KHByY29tcChkZlssMToobmNvbChkZiktMSldKSwgZGF0YT1kZiwgY29sb3VyID0gJ2dyb3VwJykrIHRoZW1lX2J3KCkgCgojIElmIHRoZSBzZXF1ZW5jaW5nIGRlcHRoIGlzIHJlYXNvbmFibHkgY29uc2lzdGVudCBhY3Jvc3MgdGhlIFJOQSBzYW1wbGVzLCB0aGVuIHRoZSBzaW1wbGVzdCBhbmQgbW9zdCByb2J1c3QgYXBwcm9hY2ggdG8gZGlmZmVyZW50aWFsIGV4aXMgdG8gdXNlIGxpbW1hLXRyZW5kLgoKZml0IDwtIGxtRml0KGV4cHJfbWF0LCBncm91cF9maWxlKQpmaXQgPC0gdHJlYXQoZml0LCBsZmM9bG9nMigxLjIpLCB0cmVuZD1UUlVFKQp0b3BUcmVhdChmaXQsIGNvZWY9bmNvbChkZXNpZ24pKQoKYGBgCgoKYGBge3J9CmxpYnJhcnkoZ2dwdWJyKQpkYXQgPC0gZXhwcl9tYXQKZGVzaWduIDwtIG1vZGVsLm1hdHJpeCh+ZmFjdG9yKGdyb3VwX2ZpbGUpKQpmaXQgPC0gbG1GaXQoZGF0LCBkZXNpZ24pCmZpdCA8LSBlQmF5ZXMoZml0KQojIG9wdGlvbnMoZGlnaXRzID0gNCkKdG9wVGFibGUoZml0LGNvZWY9MixhZGp1c3Q9J0JIJykKZGVnIDwtIHRvcFRhYmxlKGZpdCxjb2VmPTIsYWRqdXN0PSdCSCcsbnVtYmVyID0gSW5mKQpoZWFkKGRlZykgCgp3cml0ZS5jc3YoZGVnLCIuL2RhdGF0YWJsZS9zdGFibGUgdnMgdW5zdGFibGUuY3N2IikKIyMgbG9vayB1cCBGUlpCLCBTT1NULCBQUkRNNiwgT0dOCmRzMW1hcmtlcnNbZHMxbWFya2VycyRjbHVzdGVyID09ICJTTUMyIixdJGdlbmUKCmRzMm1hcmtlcnNbZHMybWFya2VycyRjbHVzdGVyID09ICJTTUMzIixdJGdlbmUKCnNtYzJtYXJrZXJzIDwtIGludGVyc2VjdChkczFtYXJrZXJzW2RzMW1hcmtlcnMkY2x1c3RlciA9PSAiU01DMiIsXSRnZW5lLCBkczJtYXJrZXJzW2RzMm1hcmtlcnMkY2x1c3RlciA9PSAiU01DMyIsXSRnZW5lKQoKCmRlZ1tpbnRlcnNlY3Qoc21jMm1hcmtlcnMsIHJvd25hbWVzKGRlZykpLF0KCmRzMW1hcmtlcnNbZHMxbWFya2VycyRjbHVzdGVyID09ICJTTUMxIixdJGdlbmUKCmRzMm1hcmtlcnNbZHMybWFya2VycyRjbHVzdGVyID09ICJTTUMxIixdJGdlbmUKClNNQzFtYXJrZXJzIDwtIGludGVyc2VjdChkczFtYXJrZXJzW2RzMW1hcmtlcnMkY2x1c3RlciA9PSAiU01DMSIsXSRnZW5lLCBkczJtYXJrZXJzW2RzMm1hcmtlcnMkY2x1c3RlciA9PSAiU01DMSIsXSRnZW5lKQoKZGVnW2ludGVyc2VjdChTTUMxbWFya2Vycywgcm93bmFtZXMoZGVnKSksXQpgYGAKCmBgYHtyfQojIGxvZ0ZDX3RocmVzaG9sZCA9IDEKIyBwdmFsdWVfdGhyZXNob2xkID0gMC4wNQpzZWxlY3RlZF9nZW5lcyA9IGFzLmNoYXJhY3RlcihyZWFkLnRhYmxlKCJTTUMyIikkVjEpCgp2b2xjYW5vX3Bsb3QgPC0gZnVuY3Rpb24oZmlsZW5hbWUsIHNlbGVjdGVkX2dlbmVzLCBsb2dGQ190aHJlc2hvbGQgPSAxLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkKewogIGY8LXJlYWQuY3N2KCIuL2RhdGF0YWJsZS9zdGFibGUgdnMgdW5zdGFibGUuY3N2IikKICBmJHRocmVzaG9sZCA8LSBmYWN0b3IoaWZlbHNlKGYkYWRqLlAuVmFsIDwgcHZhbHVlX3RocmVzaG9sZCAmIGFicyhmJGxvZ0ZDKSA+PSBsb2dGQ190aHJlc2hvbGQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZiRsb2dGQz49IGxvZ0ZDX3RocmVzaG9sZCAsJ1VwJywnRG93bicpLCdOLlMuJyksCiAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzPWMoJ1VwJywnRG93bicsJ04uUy4nKSkKICAKICAgZ2dwbG90KGYsYWVzKHg9bG9nRkMseT0tbG9nMTAoYWRqLlAuVmFsKSxjb2xvcj10aHJlc2hvbGQpKSsKICAgIGdlb21fcG9pbnQoKSsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiI0NDMDAwMCIsIiMyZjU2ODgiLCIjQkJCQkJCIikpKwogICAgZ2VvbV90ZXh0X3JlcGVsKAogICAgICBkYXRhID0gZltmJFggJWluJSBzZWxlY3RlZF9nZW5lcyxdLAogICAgICBhZXMobGFiZWwgPSBYKSwKICAgICAgc2l6ZSA9IDUsIG1heC5vdmVybGFwcyA9IDEwMDAsCiAgICAgIGNvbD0iYmxhY2siLCBzZWdtZW50LmNvbG9yID0gImJsYWNrIiwgc2hvdy5sZWdlbmQgPSBGQUxTRSApKwogICAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSkrCiAgICB0aGVtZSgKICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCksIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksCiAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLCBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCAKICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwgCiAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKQogICAgKSsKICAgIHlsYWIoJy1sb2cxMCAocC1hZGopJykgKwogICAgeGxhYignbG9nMiAoRm9sZENoYW5nZSknKSArCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9YygtbG9nRkNfdGhyZXNob2xkLGxvZ0ZDX3RocmVzaG9sZCksbHR5PTMsY29sPSJibGFjayIsbHdkPTAuNSkgKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID1jKDAsLWxvZzEwKHB2YWx1ZV90aHJlc2hvbGQpKSxsdHk9Myxjb2w9ImJsYWNrIixsd2Q9MC41KQp9CgpzZWxlY3RlZF9nZW5lcyA8LSBjKGFzLmNoYXJhY3RlcihyZWFkLnRhYmxlKCJTTUMyIikkVjEpKQoKcCA8LSB2b2xjYW5vX3Bsb3QoIi4vZGF0YXRhYmxlL3N0YWJsZSB2cyB1bnN0YWJsZS5jc3YiLHNlbGVjdGVkX2dlbmVzKSArIGdndGl0bGUoInN0YWJsZSB2cyB1bnN0YWJsZSwgU01DMiBtYXJrZXIiKQoKZ2dzYXZlKCJTTUMyX3N0YWJsZSB2cyB1bnN0YWJsZS5wbmciLHBsb3QgPSBwLGRldmljZSA9IHBuZyxoZWlnaHQgPSA0LCB3aWR0aCA9IDYpCmBgYAoKCkFkZCBhIG5ldyBjaHVuayBieSBjbGlja2luZyB0aGUgKkluc2VydCBDaHVuayogYnV0dG9uIG9uIHRoZSB0b29sYmFyIG9yIGJ5IHByZXNzaW5nICpDdHJsK0FsdCtJKi4KCldoZW4geW91IHNhdmUgdGhlIG5vdGVib29rLCBhbiBIVE1MIGZpbGUgY29udGFpbmluZyB0aGUgY29kZSBhbmQgb3V0cHV0IHdpbGwgYmUgc2F2ZWQgYWxvbmdzaWRlIGl0IChjbGljayB0aGUgKlByZXZpZXcqIGJ1dHRvbiBvciBwcmVzcyAqQ3RybCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLgoKVGhlIHByZXZpZXcgc2hvd3MgeW91IGEgcmVuZGVyZWQgSFRNTCBjb3B5IG9mIHRoZSBjb250ZW50cyBvZiB0aGUgZWRpdG9yLiBDb25zZXF1ZW50bHksIHVubGlrZSAqS25pdCosICpQcmV2aWV3KiBkb2VzIG5vdCBydW4gYW55IFIgY29kZSBjaHVua3MuIEluc3RlYWQsIHRoZSBvdXRwdXQgb2YgdGhlIGNodW5rIHdoZW4gaXQgd2FzIGxhc3QgcnVuIGluIHRoZSBlZGl0b3IgaXMgZGlzcGxheWVkLgo=